//
// Created by HP on 2022/1/31.
//

#include "test_app.h"
#include "tmc_shader.h"
#include "simple_render_system.h"
#include "movement_controller.h"

// std
#include <cassert>
#include <chrono>

namespace tmc {
    TestApp::TestApp() {
        // glad: load all OpenGL function pointers
        // ---------------------------------------
        assert(gladLoadGLLoader((GLADloadproc)glfwGetProcAddress) &&
        "Failed to initialize GLAD");

        loadGameObjects();
    }
    TestApp::~TestApp() = default;

    void TestApp::run() {
        SimpleRenderSystem simpleRenderSystem {
            R"(F:\C++\TMC\shaders\vertShader.glsl)",
            R"(F:\C++\TMC\shaders\fragShader.glsl)",
        };
        TmcCamera camera{};
        camera.setViewTarget(glm::vec3{0.f, 0.f, 0.f}, glm::vec3{0.f, 1.f, 3.0f});
        camera.setPerspectiveProjection(glm::radians(50.f),
                                        window.getAspectRatio(), 0.1f, 15.f);

        auto viewObject = TmcGameObject::createGameObject();
        MovementController cameraController{};

        auto currentTime = std::chrono::high_resolution_clock::now();

        while (!window.shouldClose()) {
            glfwPollEvents();

            float aspect = window.getAspectRatio();
            camera.setPerspectiveProjection(glm::radians(50.f), aspect, 0.1f, 15.f);

            auto newTime = std::chrono::high_resolution_clock::now();
            float frameTime = std::chrono::duration<float, std::chrono::seconds::period>
            (newTime - currentTime).count();
            currentTime = newTime;
            cameraController.moveInPlaneXZ(window.getGLFWwindow(), frameTime, viewObject);
            camera.setViewYXZ(viewObject.transform.translation, viewObject.transform.rotation);

            simpleRenderSystem.renderGameObjects(gameObjects, camera);

            window.swapBuffers();
        }
    }

    void TestApp::loadGameObjects() {
        std::shared_ptr<TmcModel> tmcModel =
                TmcModel::createModelFromFile(R"(F:\C++\TMC\models\nanosuit.obj)");
        auto flatVase = TmcGameObject::createGameObject();
        flatVase.model = tmcModel;
        flatVase.transform.translation = {.0f, 1.0f, 3.0f};
        flatVase.transform.scale = glm::vec3{.1f};
        gameObjects.push_back(std::move(flatVase));
    }
}
